require 'Object'
require 'Shot'

class Vehicle < MovableObject
  
  attr_accessor :turn_force, :move_force
  attr_accessor :components
  
  attr_reader :selected_weapon_group
  
  def initialize(image, shape)
    
    @initial_health = 100
    
    @health = @initial_health
    
    super(image, shape)
    @body.m = 5
    
    recalculate_moment
    
    @shape.collision_type = :vehicle
    
    @components = []
    
    @selected_weapon_group = 1
    
    @drift_effect = ParticleEffect.new(Images[:smoke1], 30, 20, self)
    @drift_effect.initial_scale=0.3
    @drift_effect.randomization = 30
    @drift_effect.active = false
    
    @smoke_effect = ParticleEffect.new(Images[:smoke1], 20, 10, self)
    @smoke_effect.initial_scale=0.2
    @smoke_effect.randomization = 30
    @smoke_effect.active = false
    
    @font = Gosu::Font.new($game, Gosu::default_font_name, 20)
  end
  
  def push(force)
    @shape.body.apply_force((@shape.body.a.radians_to_vec2 * (force/SUBSTEPS)), 
      CP::Vec2.new(0.0, 0.0))
  end
  
  def push_at_angle(force, angle)
    @shape.body.apply_force((angle.radians_to_vec2 * (force/SUBSTEPS)), 
      CP::Vec2.new(0.0, 0.0))
  end
  
  
  def accelerate
    engine.accelerate
  end
  
  def reverse
    engine.reverse
  end
  
  def turn_left
    engine.turn_left
  end
  
  def turn_right
    engine.turn_right
  end
  
  def aim_angle
    @body.a
  end
  
  def fire
    @components.each do |component|
      if component.is_a? Weapon and component.weapon_group == @selected_weapon_group then
        component.fire
      end
    end
  end
  
  def fire_group (group)
    weps = weapons
    weps.each { |w| 
      if w.weapon_group == group then 
        w.fire 
      end
    }
  end
  
  def select_weapon_group(group)
    @selected_weapon_group = group
  end
  
  def engine
    @components.each do |c|
      if c.is_a? Engine then
        return c
      end
    end
    nil
  end
  
  def update
    speed = @body.v.unrotate(@body.a.radians_to_vec2)
    if speed.y > 5 or speed.y < -5 then
      # we're drifting here
      #puts self.to_s + 'DRIFTING: ' + speed.y.to_s
      @drift_effect.active = true
    else
      @drift_effect.active = false
    end
    
    # smoke when damaged
    if (Float(@health) / Float(@initial_health)) < 0.3 then
      @smoke_effect.active = true
    else
      @smoke_effect.active = false
    end
    
    
    @components.each do |component|
      component.update
    end
    
    super
  end
  
  def health_percent?
    Float(@health) / Float(@initial_health)
  end
  
  def draw_hud
    
    $game.draw_quad_with_coords(vect(20, 310), 
      vect(SCREEN_WIDTH-20, SCREEN_HEIGHT-10), 0xaa000000, ZOrder::GUI)
    
    speed = @body.v.unrotate(@body.a.radians_to_vec2)
    
    # our screen-scale is 1px = 0.8m
    # therefore our speed = units/s / 0.8 == metres/s
    # so km/h = 
    
    mass_text = "Mass: %it" % @body.m
    speed_text = "Speed: %.2f km/h" % (speed.x / 800 * 60 * 20)
    health_text = "Health: %i" % @health
    wepgroup_text = "Weapon group: %i" % @selected_weapon_group
    
    @font.draw(mass_text, 30, 320,  ZOrder::GUI)
    @font.draw(speed_text, 30, 340,  ZOrder::GUI)
    @font.draw(health_text, 30, 360,  ZOrder::GUI)
    @font.draw(wepgroup_text, 30, 380,  ZOrder::GUI)
    
    weps = 0
    wep_text = ""
    @components.each do |c|
      if c.is_a? Weapon then
        weps = weps + 1
        red = ((100 - c.percent_ready) * 2.55).to_i
        green = (c.percent_ready * 2.55).to_i
        #puts red,green
        ready_colour = Gosu::Color.new(255, red, green, 0)
        wep_text = "Weapon %i: %s (%it)" % [weps, c.name, c.weight]
        @font.draw(wep_text, 30, 380 + (20 * weps),  ZOrder::GUI, 1,1,ready_colour)
      end
    end
  end
  
  def weapons_ready?
    weps = weapons
    
    weps.each {|w| if w.percent_ready == 100 or w.chamber_time < 1 then return true end }

    return false
    
  end
  
  def weapons
    weps = @components.clone
    
    #weps.reject! { |w| not(w.is_a? Weapon and w.weapon_group == @selected_weapon_group) }
    weps.reject! { |w| not(w.is_a? Weapon) }
    
    weps
  end
  
	def remove
		@drift_effect.destroy
    @smoke_effect.destroy
		super
	end
	
  def destroy
    explode
    super
  end
  
  def has_turret?
    false
  end
  
  def hurt(damage, shot)
    super
    
    flash_colour = Gosu::Color.new(0xffff0000) # red
    
    if health_percent? < 0.25 then
      flash_alpha = 0.5
    else
      flash_alpha = 0.25
    end
    
    flash_alpha = flash_alpha*255
    flash_colour.alpha = flash_alpha.to_i
    
    
    if $game.player.pawn == self then
      Flash.new(flash_colour, 0.5)
    end
  end
  
end

class Crawler < Vehicle
  def initialize(x,y)
    super(Images[:crawler], BaseShapes::Crawler)
    warp(vect(x,y))
  end
end

class Tank < Vehicle
  
  attr_reader :turret_angle
  attr_accessor :turret_turn_speed
  
  def initialize(x,y)
    super(Images[:tank_chassis], BaseShapes::Tank)
    @turret_image = Images[:tank_turret]
    warp(vect(x,y))
    @turret_angle = 0
    @turret_turn_speed = 100
  end
  
  def update
    super
    
    # make the turret turn towards the mouse
    target_pos = $game.camera.inverse_adjusted_vect($game.cursor.pos)
    
    angle = target_pos - @body.p
    
    angle = Math::atan2(angle.y, angle.x);
    
    angle = angle.radians_to_gosu
        
    turn_direction =  @turret_angle - angle

    
    turn_direction = turn_direction % 360
    turn_direction += 360 if turn_direction < 0
    
    if turn_direction < 180 then
      @turret_angle -= @turret_turn_speed * $dt
    else
      @turret_angle += @turret_turn_speed * $dt
    end
    
    if weapons_ready? then
      $game.cursor.cursor_image = Images[:cursor_target]
    else
      $game.cursor.cursor_image = Images[:cursor_target_disabled]
    end
    
  end
  
  def draw
    super
    v = $game.camera.adjusted_coords(@x,@y)
    @turret_image.draw_rot(v.x, v.y, @zindex, @turret_angle)
  end
  
  def aim_angle
    @turret_angle.gosu_to_radians
  end
  
  def has_turret?
    true
  end
end

class Jet < Vehicle
  
  def initialize(x,y)
    super(Images[:turret_gun], BaseShapes::Box)
    @body.m=1
    @height = :air
    @zindex = ZOrder::AirObjects
    warp(vect(x,y))
    
  end
  
  def update
    engine.accelerate
    super
  end
  
end

